#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <GL/glut.h>
#include "door.h"
#include "texture.h"
#include "colors.h"
#include "material.h"

/* classify a point respect to an hyperplane (>=0 the point is above the plane, <0 the point is below the plane */
#define getSign(h,p) ((h)[0]*(p)[0]+(h)[1]*(p)[1]+(h)[2])


/**************************/
float door[]={	
	4, DOOR_STRIPE,
	DOOR_END	
};

struct door_t doors[NUMBER_OF_DOORS] = 
{
/**	porta 1 **/
	{4,0,0,{50,50},{1,0},door,1.0f},
/**	porta 2 **/
	{4,0,0,{50,50},{1,0},door,1.0f},
/**	porta 3 **/
	{4,0,0,{50,50},{1,0},door,1.0f},
/**	porta 4 **/
	{4,0,0,{50,50},{1,0},door,1.0f},
/**	porta 5 **/
	{4,0,0,{50,50},{1,0},door,1.0f},
/**	porta 6 **/
	{4,0,0,{50,50},{1,0},door,1.0f},
/**	porta 7 **/
	{4,0,0,{50,50},{1,0},door,1.0f},
/**	porta 8 **/
	{4,0,0,{50,50},{1,0},door,1.0f}
};

/* find the equation of a plane in 2d from 2 points */
void findPlane(float dest[3],float p0[2],float p1[2])
{
	float x0=p0[0],y0=p0[1];
	float x1=p1[0],y1=p1[1];
	dest[0]=y1-y0;
	dest[1]=x0-x1;
	dest[2]=-x0*y1+x1*y0;
}

void drawDoor(struct door_t* door){
	
	int   I=0, dimTot /*dimensione totale del muro*/;
	float D,Z/*,K*/;
	float dimD,dimZ, /*dimK,*/U0,U1,V0,V1;
	float p0[2],p1[2],p2[2],p3[2];
	float Su,Sv;
	/*int texture = door->texture;
	 * applyTexture(texture);*/
	/*dirp rappresenta la direzione normale al muro*/
	float dirp[2]={-1*door->dir[1],door->dir[0]};
	vettore3d norm,v1,v2;
	I++;
	dimTot=door->dimTot;
	I=0;
	materials(&biancoSplendente);
	//per le porte non c'e' bisogno dei 2 cicli for per il calcolo dei pezzi di muro
	//le porte sono sempre uguali
	//vedere sulle dispense come viene disegnato il muro
	for (Z=0;dimZ=door->w[I++];Z+=dimZ)	{
		//con Z scorro il muro in altezza
		for (D=0;dimD=door->w[I++];D+=(float)fabs(dimD)){
			//con D scorro il muro in lunghezza
			if (dimD<0) continue;
			Su = dimTot/3;
			Sv = 3;
			U0 = Su*D/dimTot;
			U1 = Su*(D+dimD)/dimTot;
			V0 = Sv*Z/10;
			V1 = Sv*(Z+dimZ)/10;
			p0[0]=door->point[0]+D*door->dir[0];
			p0[1]=door->point[1]+D*door->dir[1];

			p1[0]=p0[0]+(dimD)*door->dir[0];
			p1[1]=p0[1]+(dimD)*door->dir[1];

			p2[0]=p1[0]+(door->size)*dirp[0];
			p2[1]=p1[1]+(door->size)*dirp[1];

			p3[0]=p0[0]+(door->size)*dirp[0];
			p3[1]=p0[1]+(door->size)*dirp[1];
//sotto
			glVertex3f(p0[0],p0[1],Z);
			glVertex3f(p1[0],p1[1],Z);
			glVertex3f(p2[0],p2[1],Z);
			glVertex3f(p3[0],p3[1],Z);
//sopra
			glVertex3f(p0[0],p0[1],Z+dimZ);
			glVertex3f(p1[0],p1[1],Z+dimZ);
			glVertex3f(p2[0],p2[1],Z+dimZ);
			glVertex3f(p3[0],p3[1],Z+dimZ);
//front
			glNormal3f(dirp[0],dirp[1],0.0);
			glTexCoord2f(U0,V0);
			glVertex3f(p0[0],p0[1],Z     );
			glTexCoord2f(U1,V0);
			glVertex3f(p1[0],p1[1],Z     );
			glTexCoord2f(U1,V1);
			glVertex3f(p1[0],p1[1],Z+dimZ);
			glTexCoord2f(U0,V1);
			glVertex3f(p0[0],p0[1],Z+dimZ);
//right
			glNormal3f(dirp[0],-1*dirp[1],0.0);
			glVertex3f(p1[0],p1[1],Z     );
			glVertex3f(p2[0],p2[1],Z     );
			glVertex3f(p2[0],p2[1],Z+dimZ);
			glVertex3f(p1[0],p1[1],Z+dimZ);
//back
			glNormal3f(dirp[0],-1*dirp[1],0.0);
			glTexCoord2f(U0,V0);
			glVertex3f(p2[0],p2[1],Z	);
			glTexCoord2f(U1,V0);
			glVertex3f(p3[0],p3[1],Z	);
			glTexCoord2f(U1,V1);
			glVertex3f(p3[0],p3[1],Z+dimZ);
			glTexCoord2f(U0,V1);
			glVertex3f(p2[0],p2[1],Z+dimZ);
//left
			glVertex3f(p3[0],p3[1],Z	);
			glVertex3f(p0[0],p0[1],Z	);
			glVertex3f(p0[0],p0[1],Z+dimZ);
			glVertex3f(p3[0],p3[1],Z+dimZ);
		}
	}
}


void disegnaMuroPrincipale(){
	int i;
		glEnable( GL_POLYGON_OFFSET_FILL );
		glPolygonOffset(1,1);
				applyTexture(TX_DOOR_S1);
				glPushMatrix();
					glBegin(GL_QUADS);
					for (i=0;i<NUMBER_OF_DOORS_S1;i++)
					{
						drawDoor(&doors1[i]);
					}
					glEnd();
				glPopMatrix();
		glDisable(GL_POLYGON_OFFSET_FILL);
}

void checkMovement(float Start[2],float End[2], struct door_t* last_crossed_door){
	int i;
		for (i=0;i<NUMBER_OF_DOORS;i++)
		{
			if (acrossDoor(&doors[i],Start,End, last_crossed_door))
			{
				glutPostRedisplay();
				return;
			}
		}
}

int acrossDoor(struct door_t* door,float Start[2],float End[2], struct door_t* last_crossed_door)
{
	int   I=0;
	float D;
	float dimD;
	float p0[2],p1[2];
	float h0[3],h1[3];

	/* test intersection only for the first row of the door (the one which is at z=0) */
	I++;

	last_crossed_door=0; 
	
	for (D=0;dimD=door->w[I++];D+=(float)fabs(dimD))
	{
		if (dimD<0) continue;

		p0[0]=door->point[0]+D*door->dir[0];
		p0[1]=door->point[1]+D*door->dir[1];

		p1[0]=p0[0]+(dimD)*door->dir[0];
		p1[1]=p0[1]+(dimD)*door->dir[1];

		findPlane(h0,p0,p1);
		findPlane(h1,Start,End);

		if (
				((getSign(h0,Start)>=0 && getSign(h0,End)<0 ) ||
				 (getSign(h0,Start)< 0 && getSign(h0,End)>=0)) 
			 &&
				((getSign(h1,p0   )>=0 && getSign(h1,p1 )<0 ) ||
				 (getSign(h1,p0   )< 0 && getSign(h1,p1 )>=0))
			)
		{
			last_crossed_door=door; /* to highligh a door when it is crossed */
			return 1;
		}
	}
	return 0;
}
